package com.anlogic.sdk.programfpga.ui;

import java.io.File;

import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import com.anlogic.sdk.openocd.ui.TargetSelectionWidget;
import com.anlogic.sdk.programfpga.ProgramFPGAModel;
import com.anlogic.sdk.toolpreference.utils.ProgramFPGAPrefsUtils;
import com.anlogic.sdk.utils.options.ChipType;

public class ProgramFPGADialog extends TitleAreaDialog {
	Combo chipCombo;
	Text bitFileText;
	Button bitFileBrowseButton;
	Button useOldModeButton;
	
	TargetSelectionWidget targetWidget;
	
	String[] bitFileExtensions = new String[] {".bit"};
	String[] bitFileFilters = new String[] {"*.bit"};
	
	IEclipsePreferences fpgaPrefs = ProgramFPGAPrefsUtils.getPreferences();
	
	String[] chipTypes = ChipType.getNames();
	
	protected ProgramFPGAModel model;
	
	public ProgramFPGADialog(Shell parentShell) {
		super(parentShell);
		setShellStyle(getShellStyle() | SWT.RESIZE);
	}

	protected Control createButtonBar(Composite parent) {
		Control c = super.createButtonBar(parent);
		renameOKButton();
		validate();
		return c;
	}

	private void renameOKButton() {
		Button okButton = getButton(0);
		if (okButton != null) {
			okButton.setText("Program");
			setButtonLayoutData(okButton);
		}
	}

	private void enableOkButton(boolean flag) {
		Button button = getButton(0);
		if (button != null)
			button.setEnabled(flag);
	}
	
	protected Control createDialogArea(Composite parent) {
		setTitle("Program FPGA");
		setMessage("Specify the bitstream to program device.");

		if (this.model == null) {
			this.model = new ProgramFPGAModel();
		}
		
		Composite container = new Composite(parent, SWT.DEFER);
		container.setLayout(new GridLayout(3, false));
		container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

		Label chipLabel = new Label(container, SWT.NULL);
		chipLabel.setText("Chip:");
		chipCombo = new Combo(container, SWT.POP_UP);
		GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo((Control) chipCombo);
		chipCombo.setItems(chipTypes);
		chipCombo.setData("chipCombo");
		int chipComboIndex = fpgaPrefs.getInt("chipCombo", 0);
		chipCombo.select(chipComboIndex);
		
		targetWidget = new TargetSelectionWidget(container);
		GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(targetWidget.getContainer());

		Label bitFileLabel = new Label(container, SWT.NULL);
		bitFileLabel.setText("Bitstream:");
		bitFileText = new Text(container, SWT.BORDER);
		GridDataFactory.fillDefaults().grab(true, false).applyTo((Control) bitFileText);
		String bitFile = fpgaPrefs.get("bitFileText", "");
		bitFileText.setText(bitFile);
		bitFileBrowseButton = new Button(container, SWT.PUSH);
		bitFileBrowseButton.setText("Browse");
		
		useOldModeButton = new Button(container, SWT.CHECK);
		useOldModeButton.setText("Use Old Mode");
		useOldModeButton.setSelection(true);
		
		addListeners();

		return (Control) parent;
	}
	
	private void addListeners() {
		chipCombo.addSelectionListener((SelectionListener) new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				validate();
				fpgaPrefs.putInt("chipCombo", chipCombo.getSelectionIndex());
				ProgramFPGAPrefsUtils.flush();
			}
		});

		bitFileBrowseButton.addSelectionListener((SelectionListener) new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				FileDialog dialog = new FileDialog(getShell(), SWT.OPEN);
				dialog.setFilterExtensions(bitFileFilters);
				String result = dialog.open();
				if (result != null) {
					bitFileText.setText(result);
					validate();
				}
			}
		});
		bitFileText.addModifyListener(new ModifyListener() {
			@Override
			public void modifyText(ModifyEvent e) {
				validate();
				String bitFile = bitFileText.getText();
				fpgaPrefs.put("bitFileText", bitFile);
				ProgramFPGAPrefsUtils.flush();
			}
		});
	}
	
	private void validate() {
		String bitFile = bitFileText.getText();
		File file = new File(bitFile);
		if (!file.isFile() || !file.exists()) {
			setErrorMessage("Specified file does not exits");
			enableOkButton(false);
			return;
		}
		
		boolean extensionMatched = false;
		for(String item:bitFileExtensions) {
			if(bitFile.endsWith(item)) {
				extensionMatched = true;
				break;
			}
		}
		if (!extensionMatched) {
			setErrorMessage("Please specify correct Image file");
			enableOkButton(false);
			return;
		}
		
		setErrorMessage(null);
		enableOkButton(true);
	}
	
	protected void okPressed() {
		updateModel();
		super.okPressed();
	}
	
	public void updateModel() {
		String bitFile = new Path(bitFileText.getText()).toString();
		
		this.model.setRemoteTarget(targetWidget.getSelectTarget());
		
		this.model.setHost(targetWidget.getSelectTarget().getHost());
		this.model.setPort(targetWidget.getSelectTarget().getPort());
		
		if (model.getRemoteTarget().isDefaultLocal()) {
			model.setPort(ProgramFPGAModel.PORT);
		}
		
		this.model.setBitFile(bitFile);
		this.model.setChip(chipCombo.getText());
		this.model.setUseOldMode(useOldModeButton.getSelection());
	}
	
	public ProgramFPGAModel getModel() {
		return model;
	}
}
